<?
/**
 * Copyright 2007 Melange.
 *
 * This file is part of Melange_Framework
 *
 * PHP-HTTP is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * PHP-HTTP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with PHP-HTTP; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @package http
 *
 */


// ------------------------------------------------------------------------


/**
 * Request class
 *
 * Wrapper around a <code>$_POST, $_GET and $_FILES</code>
 *
 * @category    Melange Framework
 * @package     http
 * @copyright   Copyright (c) 2007 Jeroen Simons. All rights reserved
 * @author      Jeroen Simons <jeroen@melange.nl>
 * @link        http://www.melange.nl/
 *
 */
class Request {


    // -------------------------------------------------------------- Constants


    /**
     * scheme constants
     */
    const SCHEME_HTTP  = "http";
    const SCHEME_HTTPS = "https";


    // ----------------------------------------------------- Instance Variables


    /**
     * The attributes associated with this Request, keyed by attribute name.
     *
     * @var array
     */
    protected $attributes = array();


    /**
     * Cookies parsed flag.
     */
    protected $cookiesParsed = false;


    /**
     * The content length associated with this request.
     */
    protected $contentLength = null;


    /**
     * The content type associated with this request.
     */
    protected $contentType = null;


    /**
     * The Context within which this Request is being processed.
     *
     * @var Context
     */
    protected $context = null;


    /**
     * The context path for this request.
     */
    protected $contextPath = "";


    /**
     * The default Locale if none are specified.
     *
     * @var Locale
     */
    protected $defaultLocale;


    /**
     * The preferred Locales assocaited with this Request.
     */
    protected $locales = array();


    /**
     * Parse locales.
     */
    protected $localesParsed = false;


    /**
     * The request method associated with this Request.
     */
    protected $method = null;


    /**
     * The parsed parameters for this request.  This is populated only if
     * parameter information is requested via one of the
     * <code>getParameter()</code> family of method calls.  The key is the
     * parameter name, while the value is a String array of values for this
     * parameter.
     * <p>
     * <strong>IMPLEMENTATION NOTE</strong> - Once the parameters for a
     * particular request are parsed and stored here, they are not modified.
     * Therefore, application level access to the parameters need not be
     * synchronized.
     */
    protected $parameters = null;


    /**
     * Have the parameters for this request been parsed yet?
     */
    protected $parsed = false;


    /**
     * The path information for this request.
     */
    protected $pathInfo = null;


    /**
     * The protocol name and version associated with this Request.
     */
    protected $protocol = null;


    /**
     * The query string for this request.
     */
    protected $queryString = null;


    /**
     * Was the requested session ID received in a cookie?
     */
    protected $requestedSessionCookie = false;


    /**
     * The requested session ID (if any) for this request.
     */
    protected $requestedSessionId = null;


    /**
     * Was the requested session ID received in a URL?
     */
    protected $requestedSessionURL = false;


    /**
     * The request URI associated with this request.
     */
    protected $requestURI = null;


    /**
     * The scheme associated with this Request.
     */
    protected $scheme = null;


    /**
     * Was this request received on a secure channel?
     */
    protected $secure = null;


    /**
     * The server name associated with this Request.
     */
    protected $serverName = null;


    /**
     * The server port associated with this Request.
     */
    protected $serverPort = null;


    /**
     * The currently active session for this request.
     *
     * @var Session
     */
    protected $session = null;


    /**
     * The Principal who has been authenticated for this Request.
     *
     * @var GenericPrincipal
     */
    protected $userPrincipal = null;


    // ----------------------------------------------------------- Constructors


    /**
     * Construct a new Request using a request uri
     *
     * Sets the uri instance variable
     *
     * @param string
     * @return  void
     */
    public function __construct($uri) {

        $this->defaultLocale = Locale::getDefault();
        $this->requestURI = $uri;

        // Is there a session cookie set ?
        if(!empty($_COOKIE[ini_get("session.name")])) {
            $this->setRequestedSessionCookie(true);
            $this->setRequestedSessionId(session_id());
        }

        // Set the queryString
        if (false !== ($question = strpos($uri, '?'))) {

            $this->queryString = substr($uri, $question + 1);

            // Came the sessionId with the URI ?
            if($pos = strpos($this->queryString, ini_get("session.name")."=") !== false) {
                $substr = substr($this->queryString, $pos + strlen(ini_get("session.name")));
                if($pos = strpos($substr, "&") !== false) {
                    $substr = substr($substr, 0, $pos);
                }
                $this->setRequestedSessionId($substr);
                $this->setRequestedSessionURL(true);
            }

            $this->requestURI = substr($uri, 0, $question);
        }

    }



    // --------------------------------------------------------- Public Methods


    /**
     * Return the value of the specified request attribute, if any; otherwise,
     * return <code>null</code>.  If there is more than one value defined,
     * return only the first one.
     *
     * @param name Name of the desired request attribute
     * @return mixed
     */
    public function getAttribute($name) {
        return array_key_exists($name, $this->attributes) ?
            $this->attributes[$name] : null;
    }


    /**
     * Return the names of all defined request attributes for this request.
     *
     * @return array
     */
    public function getAttributeNames() {
        return (array_keys($this->attributes));
    }


    /**
     * Remove the specified request attribute if it exists.
     *
     * @param name Name of the request attribute to remove
     * @return void
     */
    public function removeAttribute($key) {
        if (isset($this->attributes[$key])) {
            unset($this->attributes[$key]);
        }
    }


    /**
     * Set the specified request attribute to the specified value.
     *
     * @param name Name of the request attribute to set
     * @param value The associated value
     * $return void
     */
    public function setAttribute($name, $value) {

        // Name cannot be null
        if ($name === null)
            throw new Exception
                ("Name cannot be null");

        // Null value is the same as removeAttribute()
        if (is_null($value)) {
            $this->removeAttribute($name);
            return;
        }

       $this->attributes[$name] = $value;

    }


    /**
     * Return the authentication type used for this Request.
     */
    public function getAuthType() {
        return ($this->authType);
    }


    /**
     * Set the authentication type used for this request, if any; otherwise
     * set the type to <code>null</code>.  Typical values are "BASIC",
     * "DIGEST", or "SSL".
     *
     * @param authType The authentication type used
     */
    public function setAuthType($authType) {
        $this->authType = $authType;
    }


    /**
     * Return the set of Cookies received with this Request.
     */
    public function getCookies() {
        if (!$this->cookiesParsed)
            $this->parseCookies();
        return $this->cookies;

    }


    /**
     * Return the content length for this Request.
     */
    public function getContentLength() {
        if(is_null($this->contentLength))
            $this->contentLength = intval($_SERVER["CONTENT_LENGTH"]);
        return $this->contentLength;

    }


    /**
     * Return the content type for this Request.
     */
    public function getContentType() {
        if(is_null($this->contentType) && !empty($_SERVER["CONTENT_TYPE"])) {
            $contentType = $_SERVER["CONTENT_TYPE"];
            if (false !== ($semicolon = strpos($contentType, ";"))) {
                if (false !== ($charset = stripos($contentType, "charset"))) {
                    $charset = trim(substr($contentType, $charSet + 1));
                    if (false !== ($equals = strpos($charset, "="))) {
                        $this->characterEncoding = trim(substr($charset, $equals + 1));
                    }
                }
                $this->contentType = trim(substr($contentType, 0, $semicolon));
            } else {
                $this->contentType = $contentType;
            }
        }
        return ($this->contentType);

    }


    /**
     * Return the Context within which this Request is being processed.
     *
     * @return Context $this->context
     */
    public function getContext() {
        return $this->context;
    }


   /**
     *
     * Set the Context within which this Request is being processed.  This
     * must be called as soon as the appropriate Context is identified, because
     * it identifies the value to be returned by <code>getContextPath()</code>,
     * and thus enables parsing of the request URI.
     *
     * @param context The newly associated Context
     */
    public function setContext($context) {
        $this->context = $context;
        $this->contextPath = $context->getPath();
    }


   /**
     *
     * Returns the portion of the request URI that indicates the context
     * of the request.  The context path always comes first in a request
     * URI.  The path starts with a "/" character but does not end with a "/"
     * character.  For servlets in the default (root) context, this method
     * returns "". The container does not decode this string.
     *
     *
     * @return      a <code>String</code> specifying the
     *              portion of the request URI that indicates the context
     *              of the request
     */
    public function getContextPath() {
        return $this->contextPath;
    }


    /**
     *
     * Returns the name of the HTTP method with which this
     * request was made, for example, GET, POST, or PUT.
     * Same as the value of the CGI variable REQUEST_METHOD.
     *
     * @return a <code>String</code>
     *         specifying the name
     *         of the method with which
     *         this request was made
     */
    public function getMethod() {
        if(is_null($this->method))
           $this->method = $_SERVER["REQUEST_METHOD"];
        return $this->method;
    }


    /**
     * Add a parameter name and corresponding set of values to this Request.
     * (This is used when restoring the original request on a form based
     * login).
     *
     * @param name Name of this request parameter
     * @param values Corresponding values for this request parameter
     * @return void
     */
    public function addParameter($name, $values) {
        $this->parameters[$name] = $values;
    }


    /**
     * Return the value of the specified request parameter, if any; otherwise,
     * return <code>null</code>.  If there is more than one value defined,
     * return only the first one.
     *
     * @param name Name of the desired request parameter
     * @return mixed
     */
    public function getParameter($name) {

        $this->parseParameters();

        $values = array_key_exists($name, $this->parameters) ?
            $this->parameters[$name] : null;

        if ($values !== null)
            return is_array($values) ? ($values[0]) : $values;
        else
            return (null);

    }


    /**
     * Returns a <code>Map</code> of the parameters of this request.
     * Request parameters are extra information sent with the request.
     * For HTTP servlets, parameters are contained in the query string
     * or posted form data.
     *
     * @return array A <code>Map</code> containing parameter names as keys
     *  and parameter values as map values.
     */
    public function getParameterMap() {
        $this->parseParameters();
        return ($this->parameters);
    }


    /**
     * Return the names of all defined request parameters for this request.
     *
     * @return array
     */
    public function getParameterNames() {
        $this->parseParameters();
        return (array_keys($this->parameters));
    }


    /**
     * Return the defined values for the specified request parameter, if any;
     * otherwise, return <code>null</code>.
     *
     * @param name Name of the desired request parameter
     *
     * @return array
     */
    public function getParameterValues($name) {

        $this->parseParameters();

        $values = array_key_exists($name, $this->parameters) ?
            $this->parameters[$name] : null;

        if ($values !== null)
            return ($values);
        else
            return (null);

    }


    /**
     *
     * Returns any extra path information associated with
     * the URL the client sent when it made this request.
     * The extra path information follows the servlet path
     * but precedes the query string.
     * This method returns <code>null</code> if there
     * was no extra path information.
     *
     * <p>Same as the value of the CGI variable PATH_INFO.
     *
     *
     * @return      a <code>String</code>, decoded by the
     *          web container, specifying
     *          extra path information that comes
     *          after the servlet path but before
     *          the query string in the request URL;
     *          or <code>null</code> if the URL does not have
     *          any extra path information
     *
     */
    public function getPathInfo() {
        if($this->pathInfo === null)
            $this->pathInfo = $this->computePathInfo();
        return $this->pathInfo;
    }


    /**
     * @param unknown_type $pathInfo
     */
    public function setPathInfo($pathInfo) {
        $this->pathInfo = $pathInfo;
    }


    /**
     * Returns the name and version of the protocol the request uses
     * in the form <i>protocol/majorVersion.minorVersion</i>, for
     * example, HTTP/1.1. For HTTP servlets, the value
     * returned is the same as the value of the CGI variable
     * <code>SERVER_PROTOCOL</code>.
     *
     * @return      a <code>String</code> containing the protocol
     *          name and version number
     *
     */
    public function getProtocol() {
        if(is_null($this->protocol))
           $this->protocol = $_SERVER["SERVER_PROTOCOL"];
        return $this->protocol;
    }


    /**
     * Return the query string associated with this request.
     */
    public function getQueryString() {
        if(is_null($this->queryString) && !empty($_SERVER["QUERY_STRING"]))
            $this->queryString = $_SERVER["QUERY_STRING"];
        return $this->queryString;
    }


    /**
     * Sets the query string associated with this request.
     */
    public function setQueryString($queryString) {
        $this->queryString = $queryString;
    }


    /**
     * Return the request URI for this request.
     *
     * @return string
     */
    public function getRequestURI() {

        return ($this->requestURI);

    }


    /**
     * Set the unparsed request URI for this Request.
     *
     * @param uri The request URI
     * @return void
     */
    public function setRequestURI($requestURI) {
        $this->requestURI = $requestURI;
    }

    /**
     * Set a flag indicating whether or not the requested session ID for this
     * request came in through a cookie.  This is normally called by the
     * HTTP Connector, when it parses the request headers.
     *
     * @param flag The new flag
     */
    public function setRequestedSessionCookie($flag) {
        $this->requestedSessionCookie = $flag;
    }


    /**
     * Set the requested session ID for this request.  This is normally called
     * by the HTTP Connector, when it parses the request headers.
     *
     * @param id The new session id
     */
    public function setRequestedSessionId($id) {
        $this->requestedSessionId = $id;
    }


    /**
     * Set a flag indicating whether or not the requested session ID for this
     * request came in through a URL.  This is normally called by the
     * HTTP Connector, when it parses the request headers.
     *
     * @param flag The new flag
     */
    public function setRequestedSessionURL($flag) {
        $this->requestedSessionURL = $flag;
    }


    /**
     * Return <code>true</code> if the authenticated user principal
     * possesses the specified role name.
     *
     * @param role Role name to be validated
     * @return boolean
     */
    public function isUserInRole($role) {

        // Have we got an authenticated principal at all?
        if ($this->userPrincipal === null)
            return (false);

        // Identify the Realm we will use for checking role assignmenets
        if ($this->context === null)
            return (false);

        $realm = $this->context->getRealm();
        if ($realm === null)
            return (false);

        // Check for a role defined directly as a <security-role>
        return ($realm->hasRole($this->userPrincipal, $role));

    }


    /**
     * Returns the name of the scheme used to make this request,
     * for example,
     * <code>http</code>, <code>https</code>, or <code>ftp</code>.
     * Different schemes have different rules for constructing URLs,
     * as noted in RFC 1738.
     *
     * @return      a <code>String</code> containing the name
     *          of the scheme used to make this request
     *
     */
    public function getScheme() {
        if(is_null($this->scheme)) {
           switch(true) {

                case (!empty($_SERVER["HTTPS"])):
                    $this->scheme = self::SCHEME_HTTPS;
                    break;

                 // Apache1 does not export $_SERVER['HTTPS']
                case ($this->getServerPort() == 443):
                    $this->scheme = self::SCHEME_HTTPS;
                    break;

                default:
                    $this->scheme = self::SCHEME_HTTP;

            }
        }
        return $this->scheme;
    }


    /**
     * Was this request received on a secure connection?
     */
    public function isSecure() {
        if(is_null($this->secure))
           $this->secure = (!empty($_SERVER["HTTPS"]) || $this->getServerPort() == 443);
        return $this->secure;
    }


    /**
     * Returns the host name of the server that received the request.
     * For HTTP servlets, same as the value of the CGI variable
     * <code>SERVER_NAME</code>.
     *
     * @return      a <code>String</code> containing the name
     *          of the server to which the request was sent
     */
    public function getServerName() {
        if(is_null($this->serverName))
            $this->serverName = is_null($this->context->getInitParameter('SERVER_NAME')) ?
                $_SERVER["SERVER_NAME"] : $this->context->getInitParameter('SERVER_NAME');
        return $this->serverName;
    }


    /**
     * Returns the port number on which this request was received.
     * For HTTP servlets, same as the value of the CGI variable
     * <code>SERVER_PORT</code>.
     *
     * @return      an integer specifying the port number
     *
     */
    public function getServerPort() {
        if(is_null($this->serverPort))
           $this->serverPort = intval($_SERVER["SERVER_PORT"]);
        return $this->serverPort;
    }


    /**
     * Return the object bound with the specified name to the internal notes
     * for this request, or <code>null</code> if no such binding exists.
     *
     * @return Session
     */
    public function getSession() {

        if($this->session !== null)
            return $this->session;

        require_once("Session.php");
        $this->session = new Session();

        return $this->session;
    }

    /**
     * Return <code>true</code> if the session identifier included in this
     * request came from a cookie.
     */
    public function isRequestedSessionIdFromCookie() {

        if ($this->requestedSessionId !== null)
            return ($this->requestedSessionCookie);
        else
            return (false);

    }


    /**
     * Return <code>true</code> if the session identifier included in this
     * request came from the request URI.
     */
    public function isRequestedSessionIdFromURL() {

        if ($this->requestedSessionId !== null)
            return ($this->requestedSessionURL);
        else
            return (false);

    }


    /**
     * Set the Principal who has been authenticated for this Request.  This
     * value is also used to calculate the value to be returned by the
     * <code>getRemoteUser()</code> method.
     *
     * @param principal The user Principal
     * @return void
     */
    public function setUserPrincipal(GenericPrincipal $principal) {
        $this->userPrincipal = $principal;
    }


    /**
     * Return the principal that has been authenticated for this Request.
     * @return UserPrincipal
     */
    public function getUserPrincipal() {
        return ($this->userPrincipal);
    }


    // --------------------------------------------------------- Locale methods


    /**
     * Return the preferred Locale that the client will accept content in,
     * based on the value for the first <code>Accept-Language</code> header
     * that was encountered.  If the request did not specify a preferred
     * language, $the server's default Locale is returned.
     */
    public function getLocale() {

        if (!$this->localesParsed)
            $this->parseLocales();

        if (count($this->locales) > 0) {
            return ($this->locales[0]);
        } else {
            return ($this->defaultLocale);
        }

    }


    /**
     * Return the set of preferred Locales that the client will accept
     * content in, $based on the values for any <code>Accept-Language</code>
     * headers that were encountered.  If the request did not specify a
     * preferred language, $the server's default Locale is returned.
     */
    public function getLocales() {

        if (!$this->localesParsed)
            $this->parseLocales();

        if (count($this->locales) > 0)
            return ($this->locales);
        $results = array();
        $results[] = $this->defaultLocale;
        return ($results);

    }


    /**
     * Add a Locale to the set of preferred Locales for this Request.  The
     * first added Locale will be the first one returned by getLocales().
     *
     * @param locale The new preferred Locale
     */
    public function addLocale(Locale $locale) {
        $this->locales[] = $locale;
    }


    /**
     * Parse request locales.
     */
    protected function parseLocales() {

        $this->localesParsed = true;
        $this->parseLocalesHeader($_SERVER["HTTP_ACCEPT_LANGUAGE"]);

    }


    /**
     * Parse accept-language header value.
     */
    protected function parseLocalesHeader($value) {

        // Store the accumulated languages that have been requested in
        // a local collection, $sorted by the quality value ($so we can
        // add Locales in descending order).  The values will be ArrayLists
        // containing the corresponding Locales to be added
        $locales = array();

        // Preprocess the value to remove all whitespace
        $value = str_replace(" ", "", $value);

        // Process each comma-delimited language specification
        $values = explode(",", $value);
        foreach($values as $entry) {

            // Extract the quality factor for this entry
            $quality = 1.0;
            $semi = strpos($entry, ";q=");
            if ($semi !== false) {
                try {
                    $quality = doubleval(substr($entry, $semi + 3));
                } catch (Exception $e) {
                    $quality = 0.0;
                }
                $entry = substr($entry, 0, $semi);
            }

            // Skip entries we are not going to keep track of
            if ($quality < 0.00005)
                continue;       // Zero ($or effectively zero) quality factors
            if ("*" == $entry)
                continue;       // FIXME - "*" entries are not handled

            // Extract the language and country for this entry
            $language = null;
            $country = null;
            $variant = null;
            $dash = strpos($entry, '-');
            if ($dash === false) {
                $language = $entry;
                $country = "";
                $variant = "";
            } else {
                $language = substr($entry, 0, $dash);
                $country = substr($entry, $dash + 1);
                $vDash = strpos($country, '-');
                if ($vDash !== false) {
                    $cTemp = substr($country, 0, $vDash);
                    $variant = substr($country, $vDash + 1);
                    $country = $cTemp;
                } else {
                    $variant = "";
                }
            }

            if (!$this->isAlpha($language) || !$this->isAlpha($country) || !$this->isAlpha($variant)) {
                continue;
            }

            // Add a new Locale to the list of Locales for this quality level
            $locale = new Locale($language, $country, $variant);
            $key = "q_" . strval($quality * -1);  // Reverse the order

            $values = array_key_exists($key, $locales) ?
                $locales[$key] : null;

            if ($values === null) {
                $locales[$key] = array();
            }
            $locales[$key][] = $locale;


        }

        // Process the quality values in highest->lowest order ($due to
        // negating the Double value when creating the key)
        $keys = array_keys($locales);

        foreach ($keys as $key) {
            $list = $locales[$key];
            foreach ($list as $locale) {
                $this->addLocale($locale);
            }
        }

    }


    // -------------------------------------------------------- Private Methods

    /**
     * Parse cookies.
     */
    private function parseCookies() {

        require_once("Cookie.php");

        $this->cookiesParsed = true;
        $this->cookies = array();

        $serverCookies = $_COOKIE;
        unset($serverCookies[ini_get("session.name")]);
        $count = count($serverCookies);
        if ($count <= 0)
            return;

        while(list($name, $value) = each($serverCookies)) {
            $cookie = new Cookie($name, $value);
            $this->cookies[] = $cookie;
        }

    }


    /**
     * Parse the parameters of this request, if it has not already occurred.
     * If parameters are present in both the query string and the request
     * content, they are merged.
     *
     * @return void
     */
    private function parseParameters() {

        if ($this->parsed)
            return;

        if ($this->parameters === null)
            $this->parameters = array();

        // Parse any parameters specified in the query string
        parse_str($this->getQueryString(), $this->parameters);

        if (("POST" == $this->getMethod()) && ($this->getContentLength() > 0)
            && ("application/x-www-form-urlencoded" == $this->getContentType())) {

            $this->parameters += $_POST;

        } else if (("POST" == $this->getMethod()) && ($this->getContentLength() > 0)
            && ("multipart/form-data" == $this->getContentType())) {

            $this->parameters += $_POST;
            $this->parameters += $_FILES;

        }

        // Store the final results
        $this->parsed = true;

    }


    /**
     * Compute the pathinfo of this request
     *
     */
    private function computePathInfo()
    {
        $baseUrl = $this->getContextPath();

        if ((null !== $baseUrl)
            && (false === ($pathInfo = substr($this->requestURI, strlen($baseUrl))))) {
            // If substr() returns false then PATH_INFO is set to an empty string
            $pathInfo = "";
        } elseif (null === $baseUrl) {
            $pathInfo = $this->requestURI;
        }

        return (string) $pathInfo;
    }


    /**
     * Is this an alpha string ?
     *
     * @param string $value
     * @return boolean
     */
    private function isAlpha($value) {
        for ($i = 0; $i < strlen($value); $i++) {
            $c = $value[$i];
            if (preg_match("/[a-zA-Z]/", $c) == 0) {
                return false;
            }
        }
        return true;
    }

    /**
     * String representation of this request.
     *
     * @return string
     */
    public function __toString() {

        $sb = "Request[";

        $sb .= "\n\tattributes=(";
        $names = $this->getAttributeNames();
        for($i=0; $i < count($names); $i++) {
            try {
                $sb .= "\n\t\t".$names[$i]."=".is_object($this->getAttribute($names[$i])) ?
                    get_class($this->getAttribute($names[$i])) : strval($this->getAttribute($names[$i]));
                if($i < count($names) - 1)
                    $sb .= ", ";
            } catch(Exception $e) {
                ;
            }
        }
        $sb .= ")";
        $sb .= ",\n\tcontextPath=".$this->getContextPath();
        $sb .= ",\n\tisRequestedSessionIdFromCookie=".($this->isRequestedSessionIdFromCookie() ? "Yes" : "No");
        $sb .= ",\n\tisRequestedSessionIdFromUrl=".($this->isRequestedSessionIdFromUrl() ? "Yes" : "No");
        $sb .= ",\n\tlocale=".$this->getLocale();
        $sb .= ",\n\tmethod=".$this->getMethod();
//        $sb .= "\n\tnotes=(";
//        $notes = $this->getNoteNames();
//        for($i=0; $i < count($notes); $i++) {
//            try {
//                $sb .= "\n\t\t".$notes[$i]."=".is_object($this->getNote($notes[$i])) ?
//                    get_class($this->getNote($notes[$i])) : strval($this->getNote($notes[$i]));
//                if($i < count($notes) - 1)
//                    $sb .= ",";
//            } catch(Exception $e) {
//                ;
//            }
//        }
//        $sb .= ")";
        $sb .= "\n\tparameters=(";
        $parameters = $this->getParameterNames();
        for($i=0; $i < count($parameters); $i++) {
            try {
                $sb .= "\n\t\t".$parameters[$i]."=".strval($this->getParameter($parameters[$i]));
                if($i < count($parameters) - 1)
                    $sb .= ",";
            } catch(Exception $e) {
                echo $e->getMessage();
            }
        }
        $sb .= "\n\t)";
        $sb .= ",\n\tpathInfo=".$this->getPathInfo();
        $sb .= ",\n\tprotocol=".$this->getProtocol();
        $sb .= ",\n\tqueryString=".$this->getQueryString();
        $sb .= ",\n\trequestURI=".$this->getRequestURI();
        $sb .= ",\n\tscheme=".$this->getScheme();
        $sb .= ",\n\tserverName=".$this->getServerName();
        $sb .= ",\n\tserverPort=".$this->getServerPort();
        $sb .= ",\n\tuserPrincipal=".$this->getUserPrincipal();

        $sb .= "\n]";

        return $sb;

    }


}
?>